﻿namespace BM.Tools.WebControls.MForm.Design
{
    using System.Collections.Generic;
    using System.Drawing;
    using System.Windows.Forms;

    using BM.Tools.WebControls.MForm.Generator;

    /// <summary>
    /// An extension to the <see cref="TreeView"/> control that can read <see cref="FormItem" /> children tree.
    /// </summary>
    public partial class FormItemsTree : TreeView
    {
        private Dictionary<TreeNode, FormItem> nodesDictionary = new Dictionary<TreeNode, FormItem>();

        /// <summary>
        /// Initializes a new instance of the <see cref="FormItemsTree"/> class.
        /// </summary>
        public FormItemsTree()
        {
            InitializeComponent();
            CheckBoxes = true;
            
            AfterCheck += ModifyFormItem;
            BeforeCheck += CheckIfNotRoot;  
        }

        /// <summary>
        /// Creates the tree from the FormItem object.
        /// </summary>
        /// <param name="root">
        /// The root item.
        /// </param>
        public virtual void LoadFormItemTree(FormItem root)
        {
            nodesDictionary.Clear();
            Nodes.Clear();
            var rootNode = AddNodes(Nodes, root);
            rootNode.ExpandAll();
            rootNode.SelectedImageIndex = -1;
        }

        private void CheckIfNotRoot(object sender, TreeViewCancelEventArgs e)
        {            
            if (e.Node == Nodes[0] && e.Node.Checked)
            {
                e.Cancel = true;
            }
        }

        private void ModifyFormItem(object sender, TreeViewEventArgs e)
        {
            var item = nodesDictionary[e.Node];
            item.Enabled = e.Node.Checked;
            if (!item.Enabled)
            {
                ChangeColor(e.Node, Color.LightGray);
            }
            else if (AllAncestorsChecked(e.Node))
            {
                ChangeColor(e.Node, Color.Black);
            }            
        }

        private bool AllAncestorsChecked(TreeNode node)
        {
            var parent = node.Parent;
            if (parent == null)
            {
                return true;
            }

            return parent.Checked && AllAncestorsChecked(parent);
        }

        private void ChangeColor(TreeNode node, Color color)
        {
            node.ForeColor = color;
            foreach (TreeNode childNode in node.Nodes)
            {
                if (childNode.Checked)
                {                    
                    ChangeColor(childNode, color);
                }
            }
        }

        private TreeNode AddNodes(TreeNodeCollection nodes, FormItem formItem)
        {
            var node = nodes.Add(formItem.LocalName);
            nodesDictionary[node] = formItem;
            node.Checked = true;            
            foreach (var childItem in formItem.ChildrenItems)
            {
                AddNodes(node.Nodes, childItem);
            }

            return node;
        }
    }
}
